/*
 * Copyright (c) 2000
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * Written by Tom Henderson
 * Version 1.2: August 2000 
 */

#ifndef _NETINET_STP_H_
#define _NETINET_STP_H_

/***************************************************************/ 
/*                                                             */ 
/* 	stp.h:  Configurable parameters, constants, macros,    */ 
/*			function prototypes                    */
/*                                                             */ 
/***************************************************************/ 

/*
 * Flow and congestion control options
 */
#define RATE -1			/* Max rate (bits per second) (-1 to turn off)*/
#define MAXBURST 8 		/* Maximum burst size in a 10ms interval */
#define WINDOW_CONTROL 0	/* Use TCP-like congestion control */
#define RATE_CONTROL 1		/* Send at rate specified above */
#define INITIAL_CWND 1		/* Number of segments cwnd initialized to */
#define INITIAL_WINDOW 8	/* Send window used before BGN/BGNAK received */
#define NUM_DUP_ACKS 1		/* Wait for NUM_DUP_ACKS segments beyond */
				/* a loss before retransmitting          */
				/* (in TCP, it's 3, but 1 is probably OK) */
#define STP_MAXWIN 65535	/* Maximum window size (packets) */

/*
 * General configuration constants
 */
#define INITIAL_SRTT 1000	/* 1000 ms */
#define SRTT_SHIFT 3		/* srtt resolution = (1 ms >> SRTT_SHIFT) */ 
#define STP_MSS 1464 		/* 1464 + 16 (SDP) + 20 for IP = 1500 */
#define MAXBUFFER_STP 2048	/* This is the total number of outstanding */
				/* PDUs allowed.  Can be increased */

/*
 * Configuring when to POLL
 */
#define POLLS_PER_RTT 1		/* Should be >= 1 */
#define SDP_THRESHOLD 8   	/* If in window control, send a SD_POLL rather*/
				/* than regular POLL if under this threshold */
#define MIN_POLL_INTERVAL 50  	/* Minimum polling interval (ms) for short rtt*/
#define STP_POLL_LIMIT 4        /* Whenever we have sent (1/GTP_POLL_LIMIT)th */
                                /* of the buffer without polling, send a poll */
#define POLL_WITH_FIRST_BURST 1 /* If have been idle, and new data arrives */
                                /* POLL with the first burst of data */
#define MAX_POLL_TICKS 1000     /* Under normal operation, don't let the poll*/
                                /* timer get larger than this value */


/*
 * Miscellaneous options
 */
#define CLOSE_ON_QUENCH 1	/* If TRUE, shuts cwnd to 1 upon source quench*/
#define MAXSTAT 7 		/* Max. number of list elements in a STAT; */
				/* Must be odd, <= 9 to fit in mbuf */
#define TINYGRAM 100		/* (bytes) For silly window avoidance */
#define IDLE_RESTART  10	/* For persistent connections (seconds) */
				/* Note:  RFC 2581 recommends 1 RTO */


/* 
 * Configuration constants 
 */
#define TRIES_BEFORE_BACKOFF 3  /* Upon this many transmissions of a packet, */
                                /* start backing off the retransmissions */
#define STP_POLL_BACKOFF 5 	/* Exponential backoff of polling interval */
#define MAXBACKOFF 10		/* Maximum backoff is 2^MAXBACKOFF */ 
#define STP_MAXRETRANS 12	/* Maximum number of rtxs before drop */
#define MAX_CC_ATTEMPTS 6	/* backoffs of 2,4,8,16,32= 63 s. before */ 
				/* quitting */
#define STP_PERSIST 120		/* 60 seconds between persist probes */ 
#define STP_NO_PROGRESS 100	/* Kills connection if incessantly POLLing */
#define STP_KEEPALIVE 14400	/* 2 hours between keepalive probes */ 
#define STP_KEEPALIVE_INT 150	/* 75 seconds waiting for keepalive response */
#define STP_KEEPALIVE_MAX 12	/* Try 12 times in keepalive before giving up*/ 
#define STP_REROUTE 4		/* Call in_losing() upon this many retrans. */
#define STP_LINGERTIME 12000 	/* 2 minutes */

/* 
 * Constants and (relatively) static parameters 
 */
#define TRUE 1
#define FALSE 0
#define STAT 0
#define USTAT 1
#define NO_POLL 0 
#define POLL 1
#define MODULO 16777216		/* 2^24 */
#define MS_PER_TICK 10		/* 10 ms per clock tick */
#define STP_NODELAY 0x01    	/* don't delay send to coalesce packets */
#define STP_MAXSEG 0x02 	/* set max. segment size (setsocketopt) */
#define STP_CONN_DROPPED  -1	/* Return value for a dropped connection */

/*  
 * STP states
 */
#define STP_CLOSED 0x0001U    		/* 1: no connection state */
#define STP_LISTEN 0x0002U    		/* 2: recv listen, send nothing */ 
#define STP_BGN_SENT 0x0004U 		/* 4: normal active open */
#define STP_BGN_DATA_SENT 0x0008U 	/* 8: active accelerated open */
#define STP_BGN_DATA_END_SENT 0x0010U 	/* 16: active accelerated open/close */
#define STP_EST 0x0080U  		/* 128: Bidirectional established */
#define STP_CLOSE_RECV 0x0100U    	/* 256: read side closed by peer(END)*/
#define STP_HALF_CLOSE_PENDING 0x0200U	/* 512: write side closed by user */
#define STP_HALF_CLOSED 0x400U		/* 1024: write side closed by user */
#define STP_FULL_CLOSE_PENDING 0x0800U	/* 2048: both sides closed by user */
#define STP_FULL_CLOSED 0x1000U		/* 4096: wait for peer END*/
#define STP_LAST_ACK 0x2000U		/* 8192: waiting for ENDAK */

/*  
 * STP timers
 */ 
/* The following three timers are handled by the 10ms timeout routines */
#define STP_TIMER_SEND 0x01
#define STP_TIMER_BGN  0x02
#define STP_TIMER_END  0x04 
/* The following two timers are handled by stp_slowtimo() */
#define STP_TIMER_PERSIST   0x10 
#define STP_TIMER_KEEPALIVE 0x20 
/*
 * out of band data
 */
#define STPOOB_HAVEDATA 0x01
#define STPOOB_HADDATA 0x02

/*  
 * STP PDU types (8 bit unsigned field; upper 3 bits presently unused)
 */ 
#define STP_PDU_SD 0x01U     
#define STP_PDU_POLL 0x02U
#define STP_PDU_STAT 0x04U   
#define STP_PDU_USTAT 0x08U 
#define STP_PDU_BGN 0x10U
#define STP_PDU_BGNAK 0x20U
#define STP_PDU_END 0x40U
#define STP_PDU_ENDAK 0x80U 

/* Special packet types */
#define STP_PDU_URG 0xF0U
#define STP_PDU_RST 0xFFU

/* Here, define any other valid PDU concatenations */
#define STP_PDU_BGN_SD_POLL (STP_PDU_BGN | STP_PDU_SD | STP_PDU_POLL)
#define STP_PDU_BGNAK_STAT (STP_PDU_BGNAK | STP_PDU_STAT)
#define STP_PDU_BGN_SD_POLL_END (STP_PDU_BGN | STP_PDU_SD | \
                                STP_PDU_POLL | STP_PDU_END)
#define STP_PDU_BGNAK_ENDAK (STP_PDU_BGNAK | STP_PDU_ENDAK)
#define STP_PDU_SD_POLL (STP_PDU_SD | STP_PDU_POLL)
#define STP_PDU_SD_POLL_END (STP_PDU_SD | STP_PDU_POLL | STP_PDU_END)
#define STP_PDU_POLL_END (STP_PDU_POLL | STP_PDU_END)

#define IS_SD_PDU(x) ((x) & STP_PDU_SD)
#define IS_POLL_PDU(x) ((x) & STP_PDU_POLL)
#define IS_STAT_PDU(x) ((x) & STP_PDU_STAT)
#define IS_USTAT_PDU(x) ((x) & STP_PDU_USTAT)
#define IS_BGN_PDU(x) ((x) & STP_PDU_BGN)
#define IS_BGNAK_PDU(x) ((x) & STP_PDU_BGNAK)
#define IS_END_PDU(x) ((x) & STP_PDU_END)
#define IS_ENDAK_PDU(x) ((x) & STP_PDU_ENDAK)
#define IS_RST_PDU(x) (((x) & STP_PDU_RST) == STP_PDU_RST)
#define IS_URG_PDU(x) (((x) & STP_PDU_URG) == STP_PDU_URG)

/* 
 * Macros 
 */
#define	intostpcb(ip)	((struct stpcb *)(ip)->inp_ppcb)
#define	sotostpcb(so)	(intostpcb(sotoinpcb(so)))
/* Overlay the source and dest port numbers with an mbuf pointer (see tcp) */
#define REASS_MBUF_STP(si) (*(struct mbuf **)&((si)->si_s))

#define SEQ_INC(a) (((a) + 1)%MODULO)
#define SEQ_DEC(a) (((a) - 1)%MODULO)

/*
 * Debugging
 * 
 * General configuration debugging parameters 
 * Define STP_DEBUG to enable debugging/error printfs
 * Define STP_THRESHOLD to be something other than 65536 in order to enable
 *     simulated random packet losses. Also, must define STP_RANDOM_DROP to 
 *     make use of SDP_THRESHOLD
 */
/* #define STP_DEBUG */
/* #define STP_RANDOM_DROP */
#define STP_THRESHOLD 65536 	/* 
				 * Determines incoming packet drop rate. 
				 * STP_THRESHOLD/65536 determines percentage
				 * of packets successfully delivered, e.g.,
			 	 * 65536 = 100%, 64881 = 99%, 58982 = 90%, etc.
				 */

#ifdef STP_DEBUG
    void _Assert(char *, unsigned);
    #define ASSERT(f)   \
        if (f)          \
            {}          \
        else            \
            _Assert(__FILE__,__LINE__)
    #define DBG(x) x
#else
    #define ASSERT(f)
    #define DBG(x)
#endif

#endif /* !_NETINET_STP_H_ */
